/*
 * Copyright (c) 2024 HiSilicon Technologies CO., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "../inc/wifi_connect.h"
#include "MQTTClientPersistence.h" 
#include "MQTTClient.h" 
#include "errcode.h"
#include "soc_osal.h"
#include "app_init.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "cmsis_os2.h"
#include "watchdog.h"

extern int MQTTClient_init(void);

#define unused(var)     (void)(var)

#define CONFIG_WIFI_SSID            "Xiaomi 14"                              
#define CONFIG_WIFI_PWD             "w12345678"                        

#define MQTT_TASK_STACK_SIZE (1024 * 10)

uint8_t wait_flag=0;

volatile MQTTClient_deliveryToken deliveredToken;
MQTTClient client;



/* 回调函数，处理消息到达 */
void delivered(void *context, MQTTClient_deliveryToken dt) {
    unused(context);
    printf("Message with token value %d delivery confirmed\n", dt);
    deliveredToken = dt;
    return;
}

/* 回调函数，处理接收到的消息 */
int messageArrived(void *context, char *topicName, int topicLen, MQTTClient_message *message) {
    unused(context);
    unused(topicLen);
    unused(topicName);
    // printf("Current Stack Pointer: %p\n", __get_MSP());
    // printf("Message arrived on topic: %s\n", topicName);
    printf("Message: %.*s\n", message->payloadlen, (char*)message->payload);

    return 1;  // 表示消息已被处理
}

/* 回调函数，处理连接丢失 */
void connlost(void *context, char *cause) {
    unused(context);
    printf("Connection lost: %s\n", cause);
    return;
}


static errcode_t Mqtt_connect(void) {
    int rc;
    //初始化MQTT客户端
    MQTTClient_init();
    // 创建 MQTT 客户端
    rc = MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("Failed to create MQTT client, return code %d\n", rc);
        return ERRCODE_FAIL;
    }
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    conn_opts.keepAliveInterval = 35;
    conn_opts.cleansession = 1;
    #if(USE_NameAndPass)
        conn_opts.username = "name";
        conn_opts.password = "password";
    #endif

    //绑定回调函数
    MQTTClient_setCallbacks(client, NULL, NULL, NULL, NULL);

    // 尝试连接
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
        printf("Failed to connect, return code %d\n", rc);
        MQTTClient_destroy(&client);  // 连接失败时销毁客户端
        return ERRCODE_FAIL;
    }
    printf("Connected to MQTT broker!\n");

    //订阅MQTT主题
    MQTTClient_subscribe(client, TOPIC1, QOS);
    MQTTClient_subscribe(client, TOPIC2, QOS);
    printf("Subscribed to topic: %s\n", TOPIC1);
    printf("Subscribed to topic: %s\n", TOPIC2);
    wait_flag=0;

    // // 发布消息
    // MQTTClient_message pubmsg = MQTTClient_message_initializer;
    // pubmsg.payload = PAYLOAD;
    // pubmsg.payloadlen = (int)strlen(PAYLOAD);
    // pubmsg.qos = QOS;
    // pubmsg.retained = 0;

    // MQTTClient_deliveryToken token;
    // MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
    // // printf("Message published to topic: %s\n", TOPIC);

    // // 等待消息交付
    // // printf("Waiting for message delivery...\n");
    // rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
    // printf("Message delivery completed with code: %d\n", rc);

    // 断开连接
    // MQTTClient_disconnect(client, TIMEOUT);
    // MQTTClient_destroy(&client);

    return ERRCODE_SUCC;
}

int mqtt_publish(const char *topic, char* msg) {
    MQTTClient_deliveryToken token;
    int rc = 0;

    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    char* new_payload = malloc(strlen(msg) + 1);
    if (new_payload == NULL) {
        printf("Memory allocation for payload failed\n");
        return -1;
    }
    strcpy(new_payload, msg);
    pubmsg.payload = new_payload;
    pubmsg.payloadlen = (int)strlen(msg);
    pubmsg.qos = 0;
    pubmsg.retained = 0;

    if (MQTTClient_publishMessage(client, topic, &pubmsg, &token) != 0) {
        printf("Publish message error\n");
        wait_flag=1;
        free(new_payload);
        return -1;
    }
    
    MQTTClient_waitForCompletion(client, token, TIMEOUT);
    free(new_payload);
    return rc;
}


// int mqtt_publish(const char *topic, char* msg) {
//     MQTTClient_message pubmsg = MQTTClient_message_initializer;
//     MQTTClient_deliveryToken token;
//     pubmsg.payload = msg;
//     pubmsg.payloadlen = (int)strlen(msg);
//     pubmsg.qos = 0;
//     pubmsg.retained = 0;
    
//     if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0) {
//             printf("Return code from MQTT publish is %d\n", rc);
//             MQTTDisconnect(&client);
//     }
//     MQTTClient_waitForCompletion(client, token, TIMEOUT);
// }

void mqtt_receive_message(char* topic) {
    MQTTClient_message *message;
    int topicLen;
    int rc;
    // 阻塞等待接收消息
    rc = MQTTClient_receive(client, &topic, &topicLen, &message, TIMEOUT);
    if (rc == MQTTCLIENT_SUCCESS && message != NULL) {
        printf("Message arrived on topic: %.*s\n", topicLen, topic);
        if(!strcmp(topic,TOPIC2))
        {
            printf("Message: %.*s\n", message->payloadlen, (char*)message->payload);
            example_sle_server_send_notify_by_handle(message->payload,message->payloadlen);
        }

        // 释放消息
        MQTTClient_freeMessage(&message);
        free(topic);
    } else {
        printf("No message received or error occurred\n");
    }
}

int MqttClient_task(void)
{
    wifi_connect(CONFIG_WIFI_SSID,CONFIG_WIFI_PWD);
    Mqtt_connect();
    while(1)
    {
        while(wait_flag==0)
        {
            if(Receive_data[0]=='T')
            {
                if(mqtt_publish(TOPIC1,Receive_data)!=0)
                {
                    printf("publish topic1 error\r\n");
                }
            }
            if(Send_data[0]>='0'&&Send_data[0]<='9')
            {
                if(mqtt_publish(TOPIC2,Send_data)!=0)
                {
                    printf("publish topic2 error\r\n");
                }
            }
            mqtt_receive_message(TOPIC2);
            osDelay(200);
        }

    }
    return 0;
}

static void MqttClient_init(void)
{
    uapi_watchdog_disable();
    osThreadAttr_t attr;

    attr.name = "MQTT_Task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = MQTT_TASK_STACK_SIZE;
    attr.priority = osPriorityNormal5;

    if (osThreadNew((osThreadFunc_t)MqttClient_task, NULL, &attr) == NULL) {
        printf("[MQTT_Demo] Failed to create MQTTTask!\n");
    }
    // osal_task *task_handle = NULL;

    // osal_kthread_lock();
    // task_handle = osal_kthread_create((osal_kthread_handler)MqttClient_task, 0, "WiFiStaTask", WIFI_STA_TASK_STACK_SIZE);
    // if (task_handle != NULL) {
    //     osal_kthread_set_priority(task_handle, WIFI_STA_TASK_PRIO);
    //     osal_kfree(task_handle);
    // }
    // osal_kthread_unlock();
}
app_run(MqttClient_init);
/* Run the example_wifi_sta_entry. */